﻿using System;
using System.Security.Principal;
using System.Web;
using System.Web.Mvc;
using ExcellentCRM.Site.Utilities;

namespace ExcellentCRM.Site.Filters
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
    public class SiteAuthAttribute : FilterAttribute, IAuthorizationFilter
    {
        protected virtual bool AuthorizeCore(HttpContextBase httpCtx)
        {
            if (httpCtx == null)
            {
                throw new ArgumentNullException("httpCtx");
            }

            IPrincipal user = httpCtx.User;
            return user.Identity.IsAuthenticated && httpCtx.Session[PresetValues.SessionKeys.CurrentAcctId] != null;
        }

        protected virtual HttpValidationStatus OnCacheAuthorization(HttpContextBase httpCtx)
        {
            if (httpCtx == null)
            {
                throw new ArgumentNullException("httpCtx");
            }

            bool isAuthorized = AuthorizeCore(httpCtx);
            return (isAuthorized)
                       ? HttpValidationStatus.Valid
                       : HttpValidationStatus.IgnoreThisRequest;
        }

        private void CacheValidateHandler(HttpContext context, object data,
                                          ref HttpValidationStatus validationStatus)
        {
            validationStatus = OnCacheAuthorization(new HttpContextWrapper(context));
        }

        public void OnAuthorization(AuthorizationContext filterCtx)
        {
            if (filterCtx == null)
                throw new ArgumentNullException("filterCtx");
            if (filterCtx.ActionDescriptor.IsDefined(typeof (AllowAnonymousAttribute), true) ||
                filterCtx.ActionDescriptor.ControllerDescriptor.IsDefined(typeof (AllowAnonymousAttribute), true))
                return;
            if (AuthorizeCore(filterCtx.HttpContext))
            {
                HttpCachePolicyBase cachePolicy = filterCtx.HttpContext.Response.Cache;
                cachePolicy.SetProxyMaxAge(new TimeSpan(0));
                cachePolicy.AddValidationCallback(CacheValidateHandler, null);
            }
            else
                filterCtx.Result = new HttpUnauthorizedResult();
        }
    }
}